package com.chaos.system.controller;

import cn.hutool.core.util.ObjectUtil;
import com.chaos.auth.api.feign.Oauth2Feign;
import com.chaos.framework.model.dto.ID;
import com.chaos.framework.model.dto.result.data.BooleanResult;
import com.chaos.framework.model.dto.result.data.DataResult;
import com.chaos.framework.model.dto.result.list.ListResult;
import com.chaos.framework.model.enums.ShowTypeEnums;
import com.chaos.framework.model.helper.IDHelper;
import com.chaos.framework.model.helper.ListHelper;
import com.chaos.framework.model.serivce.RedisService;
import com.chaos.framework.starter.base.BaseController;
import com.chaos.framework.starter.helper.CheckHelper;
import com.chaos.system.api.data.RbacMenuData;
import com.chaos.system.api.data.RbacRoleMenuBtnData;
import com.chaos.system.api.data.RbacUserData;
import com.chaos.system.api.data.RbacUserRoleData;
import com.chaos.system.api.data.TTenantData;
import com.chaos.system.api.dto.TTenantIndexDto;
import com.chaos.system.dto.RbacMenuRouteDto;
import com.chaos.system.dto.RbacRoleMenuBtnDto;
import com.chaos.system.dto.RbacUserCurrentDto;
import com.chaos.system.dto.SendCaptchaDto;
import com.chaos.system.dto.VerifyCaptchaDto;
import com.chaos.system.entity.RbacUser;
import com.chaos.system.enums.CorrelationTypeEnums;
import com.chaos.system.service.RbacMenuService;
import com.chaos.system.service.RbacRoleMenuBtnService;
import com.chaos.system.service.RbacUserRoleService;
import com.chaos.system.service.RbacUserService;
import com.chaos.system.service.TTenantService;
import com.chaos.system.service.tencent.SmsBizService;
import com.chaos.system.api.enums.SmsType;
import com.chaos.system.service.tencent.TencentSmsService;
import io.swagger.annotations.ApiOperation;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Jacky.Cui
 * @since 2024-12-02
 */
@Slf4j
@RestController
@RequestMapping("/index")
public class IndexAdminController extends BaseController {
    @Resource
    private TTenantService tTenantService;
    @Resource
    private TencentSmsService tencentSmsService;
    @Resource
    private SmsBizService smsBizService;
    @Resource
    private RedisService redisService;
    @Resource
    private RbacUserService rbacUserService;
    @Resource
    private Oauth2Feign oauth2Feign;
    @Resource
    private RbacMenuService rbacMenuService;
    @Resource
    private RbacUserRoleService rbacUserRoleService;
    @Resource
    private RbacRoleMenuBtnService rbacRoleMenuBtnService;

    @PostMapping("/tTenant/list.admin")
    public ListResult<TTenantIndexDto> list() {
        return listResult(tTenantService.listIndex());
    }


    @PostMapping("/sendCaptcha.admin")
    @ApiOperation(value = "发送验证码", httpMethod = "POST")
    public BooleanResult sendCaptcha(@RequestBody SendCaptchaDto data) {
        CheckHelper.requireNotNull(data, "不能为空");
        CheckHelper.requireNotBlank(data.getPhone(), "手机号不能为空");
        CheckHelper.requireNotNull(data.getSmsCode(), "smsCode不能为空");


        SmsType smsType = SmsType.getByCode(data.getSmsCode());
        CheckHelper.requireNotNull(smsType, "smsType不存在");
        ArrayList<String> params = smsBizService.getParamsByType(smsType);

        String captcha = smsBizService.generateCaptcha();
        long expireTime = 5 * 60;
        String key = String.format("phone_captcha:%s:%s", smsType.getCode(), data.getPhone());

        redisService.set(key, captcha, expireTime);
        // tencentSmsService.send(data.getPhone(), smsType.getTemplateId(), params);
        return booleanResult(true);
    }

    @PostMapping("/verifyCaptcha.admin")
    @ApiOperation(value = "验证验证码", httpMethod = "POST")
    public BooleanResult verifyCaptcha(@RequestBody VerifyCaptchaDto data) {
        CheckHelper.requireNotNull(data, "请求数据不能为空");
        CheckHelper.requireNotBlank(data.getPhone(), "手机号不能为空");
        CheckHelper.requireNotNull(data.getSmsCode(), "smsCode不能为空");
        CheckHelper.requireNotNull(data.getCaptcha(), "captcha不能为空");


        SmsType smsType = SmsType.getByCode(data.getSmsCode());
        CheckHelper.requireNotNull(smsType, "smsType不存在");

        String key = String.format("phone_captcha:%s:%s", smsType.getCode(), data.getPhone());
        String captcha = (String) redisService.get(key);
        CheckHelper.requireNotBlank(captcha, "验证码已过期");
        CheckHelper.requireEquals(captcha, data.getCaptcha(), "验证码错误");
        redisService.del(key);
        RbacUserData admin = rbacUserService.selectByMobile(data.getPhone());
        CheckHelper.requireNotNull(admin, "管理员不存在");
        boolean res = false;
        if (smsType.equals(SmsType.FORGET_PASSWORD)) {
            DataResult<String> result = oauth2Feign.passwordEncoder(data.getPassword());
            CheckHelper.requireSuccess(result, "密码加密失败");
            CheckHelper.requireNotBlank(result.getData(), "密码加密失败");
            admin.setPassword(result.getData());
            res = rbacUserService.updateModelByID(admin);
        }
        return booleanResult(res);
    }

    @PostMapping("/current.admin")
    public DataResult<RbacUserCurrentDto> current() {
        Long adminId = getAdminId();
        if (ObjectUtil.isNull(adminId)) {
            return dataResult(RbacUserCurrentDto.builder().build());
        }
        RbacUser user = rbacUserService.getById(adminId);
        CheckHelper.requireNotNull(user, "管理员不存在");
        RbacUserCurrentDto dto = RbacUserCurrentDto.builder().avatar(user.getAvatar()).status(user.getStatus()).username(user.getUsername()).build();
        dto.setId(adminId);
        return dataResult(dto);
    }


    @PostMapping("/current/routes/list.admin")
    @ApiOperation(value = "获取路由", httpMethod = "POST")
    public ListResult<RbacMenuRouteDto> routes() {
        Long adminId = getAdminId();
        if (ObjectUtil.isNull(adminId)) {
            return listResult(Lists.newArrayList());
        }

        List<RbacUserRoleData> roles = rbacUserRoleService.selectByData(RbacUserRoleData.builder().userId(adminId).build());
        Set<Long> roleIds = ListHelper.getFieldSet(roles, RbacUserRoleData::getRoleId);
        if (ObjectUtil.isEmpty(roleIds)) {
            return listResult(Lists.newArrayList());
        }
        Set<Long> menuIds;
        if (isSuperAdminRolePresent(roleIds)) {
            // 超级管理员拥有所有菜单
            List<RbacMenuData> menus = rbacMenuService.selectByData(RbacMenuData.builder().build());
            menuIds = ListHelper.getFieldSet(menus, RbacMenuData::getId);
        }
        else {
            RbacRoleMenuBtnDto query = RbacRoleMenuBtnDto.builder().roleIds(roleIds).correlationType(CorrelationTypeEnums.MENU.getCode()).build();
            List<RbacRoleMenuBtnData> menus = rbacRoleMenuBtnService.selectByData(query);
            menuIds = ListHelper.getFieldSet(menus, RbacRoleMenuBtnData::getMenuOrBtnId);
        }

        if (menuIds.isEmpty()) {
            return listResult(Lists.newArrayList());
        }
        List<RbacMenuData> menuList = rbacMenuService.selectByIds(IDHelper.ids(menuIds));
        if (menuList.isEmpty()) {
            return listResult(Lists.newArrayList());
        }

        List<RbacMenuRouteDto> routes = convertToAntDesignRoutes(menuList);

        return listResult(routes);


    }

    private boolean isSuperAdminRolePresent(Set<Long> roleIds) {
        Long superAdminRoleId = 1L;
        return roleIds.contains(superAdminRoleId);
    }

    //构建菜单
    private List<RbacMenuRouteDto> convertToAntDesignRoutes(List<RbacMenuData> menuList) {
        // 创建一个 map 以便通过 parentId 快速查找子菜单
        Map<Long, List<RbacMenuData>> menuMap = new HashMap<>();
        for (RbacMenuData menu : menuList) {
            menuMap.computeIfAbsent(menu.getParentId(), k -> new ArrayList<>()).add(menu);
        }

        // 找到所有顶级菜单项
        List<RbacMenuRouteDto> routes = new ArrayList<>();
        for (RbacMenuData menu : menuList) {
            if (menu.getParentId() == null || menu.getParentId() == 0) {
                addRoute(menuMap, routes, menu);
            }
        }

        return routes;
    }

    // 递归构建子路由
    private List<RbacMenuRouteDto> buildChildRoutes(Long parentId, Map<Long, List<RbacMenuData>> menuMap) {
        List<RbacMenuRouteDto> childRoutes = new ArrayList<>();
        List<RbacMenuData> children = menuMap.getOrDefault(parentId, Collections.emptyList());
        for (RbacMenuData menu : children) {
            addRoute(menuMap, childRoutes, menu);
        }
        return childRoutes;
    }

    private void addRoute(Map<Long, List<RbacMenuData>> menuMap, List<RbacMenuRouteDto> routes, RbacMenuData menu) {
        RbacMenuRouteDto route = new RbacMenuRouteDto();
        route.setPath(menu.getPath());
        route.setName(menu.getName());
        route.setIcon(menu.getIcon());
        route.setRoutes(buildChildRoutes(menu.getId(), menuMap));
        routes.add(route);
    }

    @PostMapping("/current/tenant.admin")
    @ApiOperation(value = "当前租户详情", httpMethod = "POST")
    public DataResult<TTenantData> currentTenant() {
        Long tenantId = getTenantId();
        return dataResult(tTenantService.selectByID(new ID(tenantId)));

    }

    @PostMapping("/logout.admin")
    public BooleanResult logout() {
        return booleanResult(true);
    }


}
